package jdklearning.reflect.method;



/**
 * 看到运行结果后，感觉真是6不行，接着就想为什么？Main$inner有意料之中，但Main$1哪里来的？我想了很久，只知道这个类是怎么出来的，大概出来是为了什么，但具体的实现也没搞明白。
 * 　　看代码，有很突兀和很关键的一句：new inner(); 就是这句话生成了Main$1类。
 * 　　随后，跟着疑问来了？这句话怎么会生成Main$1类呢？new inner();不是有inner类吗？不是Main$inner这个类的对象吗？
 * 　　要理解这其中的原理首先要明白：Java对于每一个类都是看作顶层类的，哪怕所谓的嵌套类（内部类）编译后都会生成一个单独类文件
 * ，这也是为什么会生成Main$inner的原理，也就是说，编译后，内外部两个类表面上其实就没啥关系了
 * （但是内部非静态类只有外部类可以访问，这种权限认定不知道怎么实现的），然后Main$1是怎么回事呢？
 * 　　这里眼亮的可能看到了：inner这个内部类是私有的，私有内部类。前面知道
 * ，拥有内部类的类编译后内外部类两者没有关系，那么私有内部类编译后默认是没有对外构造器的
 * （如果以上代码中在Inner手动给一个public的构造器，Main$1是不会出现的），但是我们又知道
 * ，外部类是可以引用内部类的，那么编译后，又是两个毫无关系的类，一个类没对外构造器
 * ，但另一个类确实是有对这个类的实例对象权限（这里就是重点，内部类哪怕没有public构造器
 * ，外部类都有实例化内部类对象的权限）的，这种情况下编译器就会生成一个合成类
 * ，也就是Main$1，一个什么也没有的空类（是的，什么也没有，连构造器都没有）。
 * 　　但到这里，仍然不明白其实现原理是怎么样的，原先以为合成类是那个内部类的副本
 * ，外部类访问内部类，在编译器认为只是和合成类交互，只是合成类只有外部类有权限访问，但是事实上
 * ，不管内部类怎么变化，合成类只是一个空的类，有点类似标记作用（真正作用却是不得而知）。
 *
 * 总结
 * synthetic总的来说，是由编译器引入的字段、方法、类或其他结构，主要用于JVM内部使用，为了遵循某些规范而作的一些小技巧从而绕过这些规范，有点作弊的感觉，只不过是由编译器光明正大的，人为是没有权限的（但事实上有时候还是能被利用到的）。
 *
 * https://blog.csdn.net/a327369238/article/details/52608805
 * @author shenenlu 2021年06月18日 下午16:40:02
 */
public class SyntheticMethod2 {


    private static class Inner {

    }

    static void checkSynthetic (String name) {
        try {
            System.out.println (name + " : " + Class.forName (name).isSynthetic ());
        } catch (ClassNotFoundException exc) {
            exc.printStackTrace (System.out);
        }
    }
    public static void main(String[] args) throws Exception{
        /**
         *打印结果：
         * jdklearning.reflect.method.SyntheticMethod2 : false
         * jdklearning.reflect.method.SyntheticMethod2$Inner : false
         * jdklearning.reflect.method.SyntheticMethod2$1 : true
         * //编译结果，生成三个class文件: Main.class/Main$inner/Main$1.class
         * // $FF: synthetic class
         * class Main$1 {
         * }
         */
        new Inner ();
        checkSynthetic ("jdklearning.reflect.method.SyntheticMethod2");
        checkSynthetic ("jdklearning.reflect.method.SyntheticMethod2$Inner");
        checkSynthetic ("jdklearning.reflect.method.SyntheticMethod2$1");
    }


}
